package task3;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class MyConnectionPool {

	class MyConnection {
		int _ID;

		MyConnection(final int id) {
			_ID = id;
		}
	}

	class MyTask implements Runnable {
		int _ID;
		MyConnection mc;

		MyTask(final int id) {
			_ID = id;
		}

		public void run() {
			Random r = new Random();

			System.out.println("Task " + _ID + " started working...");
			try {
				System.out.println("Task " + _ID + " waiting for connection...");
				mc = checkout();
				System.out.println("Task " + _ID + " got access to connection...");
				
				int workingTime = r.nextInt(THREAD_SLEEP_CEILING);
				
				if (workingTime < IDLE_TIMEOUT) {
					Thread.sleep(workingTime);
					checkin(mc);
					System.out.println("Task " + _ID +
							" finished working with connection...");
				} else {
					Thread.sleep(IDLE_TIMEOUT);
					checkin(mc);
					System.out.println("Task " + _ID +
							" released connection due to timeout...");
				}
			} catch (Exception e) {
				e.printStackTrace(System.err);
			}
		}
	}

	private static final int DEFAULT_POOL_CAPACITY = 10;
	private static final int WAITING_TIMEOUT = 2000;
	private static final int IDLE_TIMEOUT = 3000;
	private static final int THREAD_SLEEP_CEILING = 5000;

	private List<MyConnection> connections;
	private static int MAX_CONNS;

	private String mUrl = "";
	private String mUser = "";
	private String mPasswd = "";

	private Semaphore semaphore;

	public MyConnectionPool(String url, String user, String passwd) {
		this(url, user, passwd, DEFAULT_POOL_CAPACITY);
	}

	public MyConnectionPool(String url, String user, String passwd, int maxConns) {
		MAX_CONNS = maxConns;
		mUrl = mUrl.concat(url);
		mUser = mUser.concat(user);
		mPasswd = mPasswd.concat(passwd);
		connections = createConnections();
		semaphore = new Semaphore(MAX_CONNS);
	}

	private List<MyConnection> createConnections() {
		List<MyConnection> conns = new ArrayList<MyConnection>(MAX_CONNS);
		for (int i = 0; i < MAX_CONNS; i++) {
			conns.add(new MyConnection(i));
		}
		return conns;
	}

	public MyConnection checkout() throws InterruptedException {
		if (semaphore.tryAcquire(WAITING_TIMEOUT, TimeUnit.MILLISECONDS)) {
			return connections.remove(0);
		} else {
			throw new InterruptedException("WAITING TIMEOUT EXPIRED!");
		}
	}

	public void checkin(MyConnection c) {
		connections.add(c);
		semaphore.release();
	}
}